package libs

import (
	"crypto/sha256"
	"encoding/hex"
	"fmt"
	"github.com/duanshanghanqing/godash"
	"os"
	"os/signal"
	"sync"
	"syscall"
	"time"
)

func MappingStruct(l interface{}, r interface{}) {
	godash.MappingStruct(l, r)
}

func GetSha256(str string) string {
	srcByte := []byte(str)
	sha256New := sha256.New()
	sha256Bytes := sha256New.Sum(srcByte)
	sha256String := hex.EncodeToString(sha256Bytes)
	return sha256String
}

// 实现通用定时器

// Fn 定义函数类型
type Fn func() error

// Ticker 定时器中的成员
type Ticker struct {
	Tick   *time.Ticker
	Runner Fn
}

// NewTick 创建定时器对象
func NewTick(interval int, f Fn) *Ticker {
	return &Ticker{
		Tick:   time.NewTicker(time.Duration(interval) * time.Second), // 隔多少秒执行一次
		Runner: f,                                                     // 回调函数
	}
}

// Start 启动定时器需要执行的任务
func (t *Ticker) Start() {
	for {
		select {
		case <-t.Tick.C:
			t.Runner()
		}
	}
}

// Signal 实现全局监听优雅退出
var signalFuncList []func(err error)
var onceSignal sync.Once

func Signal(f func(err error)) {
	// 保证在并发场景只执行一次，这里主要不想让监听到多次
	onceSignal.Do(func() {
		// 监听程序退出
		go func() {
			// 信号同步管道
			signalChan := make(chan os.Signal)
			// https://www.jianshu.com/p/ae72ad58ecb6
			// ctrl + c 信号 syscall.SIGINT
			// pkill 信号 syscall.SIGTERM
			signal.Notify(signalChan, syscall.SIGINT, syscall.SIGTERM) // 写入信号
			// 退出写入错误
			//errChan <- fmt.Errorf("%s", <-signalChan) // 一旦能读到信号，就说明有错误，这里会阻塞
			err := fmt.Errorf("%s", <-signalChan)
			for _, v := range signalFuncList {
				v(err)
			}
		}()
	})
	signalFuncList = append(signalFuncList, f)
}
